package org.zpmis.api.business;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.transaction.annotation.Transactional;
import org.zpmis.common.base.AdminLoginUser;
import org.zpmis.common.base.BaseWebService;
import org.zpmis.common.exception.BusinessException;
import org.zpmis.common.result.ResultCode;
import org.zpmis.common.utils.StringUtil;
import org.zpmis.domain.project.enums.ProjectTaskEnum;
import org.zpmis.domain.project.model.Project;
import org.zpmis.domain.project.model.ProjectTask;
import org.zpmis.domain.project.model.TaskTransferLog;
import org.zpmis.domain.project.qo.*;
import org.zpmis.domain.project.service.ProjectService;
import org.zpmis.domain.project.service.ProjectTaskService;
import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.zpmis.domain.project.service.TaskTransferLogService;
import org.zpmis.domain.project.vo.GetTaskDetailVo;
import org.zpmis.domain.project.vo.ProjectTaskListVo;
import org.zpmis.domain.project.vo.SubTaskQueryVo;
import org.zpmis.domain.project.vo.TaskDetailVo;
import org.zpmis.domain.project.vo.TaskTransferLogVo;
import org.zpmis.domain.user.model.Employee;
import org.zpmis.domain.user.model.SysUser;
import org.zpmis.domain.user.service.EmployeeService;
import org.zpmis.domain.user.service.SysUserService;
import tk.mybatis.mapper.entity.Condition;
import tk.mybatis.mapper.entity.Example;

import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Created with CodeGenerator
 * Description:
 * @author  Yang
 * Date: 2021-6-2
 * Time: 14:53:29
 */
@Service
@Slf4j
public class ProjectTaskWebService extends BaseWebService {
     @Reference
     private ProjectTaskService projectTaskService;

     @Reference
     private TaskTransferLogService taskTransferLogService;

     @Reference
     private SysUserService sysUserService;

    @Reference
    private EmployeeService employeeService;

    @Reference
    private ProjectService projectService;

    /**
     * 新增项目任务
     * @param addProjectTaskQo
     * @throws BusinessException
     * @throws Exception
     */
    public void addProjectTask(AddProjectTaskQo addProjectTaskQo) throws BusinessException,Exception {
        //获取当前登录用户
        AdminLoginUser adminLoginUser = super.getAdminLoginUser();
        if(adminLoginUser == null){
            throw new BusinessException(ResultCode.USER_NOT_LOGIN);
        }

        projectTaskService.save(
            //封装新增数据到实体类中
            ProjectTask.builder()
                    .name(addProjectTaskQo.getName())
                    .type(addProjectTaskQo.getType())
                    .projectId(addProjectTaskQo.getProjectId())
                    .level(addProjectTaskQo.getLevel())
                    .parentId(addProjectTaskQo.getParentId() == null ? 0 : addProjectTaskQo.getParentId())
                    .description(addProjectTaskQo.getDescription())
                    .descAttachment(addProjectTaskQo.getDescAttachment())
                    .planStartTime(addProjectTaskQo.getPlanStartTime())
                    .planEndTime(addProjectTaskQo.getPlanEndTime())
                    .startTime(addProjectTaskQo.getStartTime())
                    .endTime(addProjectTaskQo.getEndTime())
                    .workHours(getHours(addProjectTaskQo.getStartTime(),addProjectTaskQo.getEndTime()))//计算工时
                    .sysUid(addProjectTaskQo.getSysUid())
                    .completeResult(addProjectTaskQo.getCompleteResult())
                    .resultAttachment(addProjectTaskQo.getResultAttachment())
                    .createPerson(adminLoginUser.getUserName())
                    .createId(adminLoginUser.getId())
                    .status(addProjectTaskQo.getStatus() == null ? ProjectTaskEnum.NEW_BUILD_STATUS.code() : addProjectTaskQo.getStatus())
                    .createTime(Instant.now().toEpochMilli())
                    .isDeleted(ProjectTaskEnum.NOT_DELETE.code())
                    .progress(addProjectTaskQo.getProgress())
                    .build()
        );
    }

    /**
     * 修改项目任务
     * @param editProjectTaskQo
     * @throws BusinessException
     * @throws Exception
     */
    public void editProjectTask(EditProjectTaskQo editProjectTaskQo) throws BusinessException,Exception{
        Long id = editProjectTaskQo.getId();
        ProjectTask projectTask = projectTaskService.findById(id);
        if(projectTask == null){
            throw new BusinessException(ResultCode.DATA_NOT_FOUND);
        }
        projectTask.setName(editProjectTaskQo.getName());
        projectTask.setType(editProjectTaskQo.getType());
        projectTask.setLevel(editProjectTaskQo.getLevel());
        projectTask.setDescription(editProjectTaskQo.getDescription());
        projectTask.setDescAttachment(editProjectTaskQo.getDescAttachment());
        projectTask.setPlanStartTime(editProjectTaskQo.getPlanStartTime());
        projectTask.setPlanEndTime(editProjectTaskQo.getPlanEndTime());
        projectTask.setStartTime(editProjectTaskQo.getStartTime());
        projectTask.setEndTime(editProjectTaskQo.getEndTime());
        //计算工时
        projectTask.setWorkHours(getHours(editProjectTaskQo.getStartTime(), editProjectTaskQo.getEndTime()));
        projectTask.setSysUid(editProjectTaskQo.getSysUid());
        projectTask.setCompleteResult(editProjectTaskQo.getCompleteResult());
        projectTask.setResultAttachment(editProjectTaskQo.getResultAttachment());
        projectTask.setProgress(editProjectTaskQo.getProgress());
        projectTask.setStatus(editProjectTaskQo.getStatus());
        projectTaskService.update(projectTask);
    }

    /**
     * 项目任务 逻辑删除 只有新建的任务状态才可以删除
     * @param delProjectTaskQo
     * @throws BusinessException
     * @throws Exception
     */
    public void delProjectTask(DelProjectTaskQo delProjectTaskQo) throws BusinessException,Exception{
        Long id = delProjectTaskQo.getId();
        ProjectTask projectTask = projectTaskService.findById(id);
        if(projectTask == null){
            throw new BusinessException(ResultCode.DATA_NOT_FOUND);
        }
        if(projectTask.getStatus() != ProjectTaskEnum.NEW_BUILD_STATUS.code()){
            throw new BusinessException(ResultCode.NO_PERMISSION);
        }
        //根据父id查询子任务集合 如果存在子任务 则无法删除
        Condition condition = new Condition(ProjectTask.class);
        Example.Criteria criteria = condition.createCriteria();
        criteria.andEqualTo("parentId",id);
        List<ProjectTask> subProjectTaskList = projectTaskService.findByCondition(condition);
        if(!subProjectTaskList.isEmpty()){
            throw new BusinessException(ResultCode.DATA_ALREADY_RELATION_EXISTS);
        }
        projectTaskService.update(
                ProjectTask.builder()
                .id(id)
                .isDeleted(ProjectTaskEnum.DELETED.code())
                .build()
        );
    }

    /**
     * 项目任务列表查询
     * @param projectTaskListQo
     * @return
     */
    public PageInfo projectTaskList(ProjectTaskListQo projectTaskListQo) {
        String name = projectTaskListQo.getName();
        Integer level = projectTaskListQo.getLevel();
        Integer type = projectTaskListQo.getType();
        Integer status = projectTaskListQo.getStatus();
        Long startTime = projectTaskListQo.getStartTime();
        Long endTime = projectTaskListQo.getEndTime();
        Condition condition = new Condition(ProjectTask.class);
        Example.Criteria criteria = condition.createCriteria();
        criteria.andEqualTo("isDeleted",ProjectTaskEnum.NOT_DELETE.code());
        criteria.andEqualTo("parentId",0);

        if(StringUtil.isNotEmpty(name)){
            criteria.andLike("name","%"+name+"%");
        }
        if(level != null){
            criteria.andEqualTo("level",level);
        }
        if(type != null){
            criteria.andEqualTo("type",type);
        }
        if(status != null){
            criteria.andEqualTo("status",status);
        }
        if(startTime != null && endTime != null){
            criteria.andGreaterThanOrEqualTo("createTime",startTime);
            criteria.andLessThanOrEqualTo("createTime",endTime);
        }
        if(startTime != null && endTime == null){
            criteria.andGreaterThanOrEqualTo("createTime",startTime);
            criteria.andLessThanOrEqualTo("createTime",Instant.now().toEpochMilli());
        }
        if(startTime == null && endTime != null){
            criteria.andLessThanOrEqualTo("createTime",endTime);
        }
        condition.orderBy("createTime").desc();
        PageHelper.startPage(projectTaskListQo.getPageNum(),projectTaskListQo.getPageSize());
        List<ProjectTask> projectTaskList = projectTaskService.findByCondition(condition);
        PageInfo pageInfo = new PageInfo(projectTaskList);
        //返回自定义对象
        //List<ProjectTaskListVo> resultList = projectTaskList.stream().map(ProjectTaskListVo::new).collect(Collectors.toList());
        List<SubTaskQueryVo> taskQueryVoList = projectTaskList.stream().map(SubTaskQueryVo::new).collect(Collectors.toList());
        List<SubTaskQueryVo> subTaskQueryVos = this.recursiveQuery(taskQueryVoList);
        //显示指派人名称
        subTaskQueryVos.stream().forEach(subTaskQueryVo -> {
            if(subTaskQueryVo.getSysUid() != null){
                Employee employee = employeeService.findBy("sysUid", subTaskQueryVo.getSysUid());
                if(employee != null){
                    subTaskQueryVo.setSysUserName(employee.getName());
                }else{
                    SysUser sysUser = sysUserService.findById(subTaskQueryVo.getSysUid());
                    if(sysUser != null){
                        subTaskQueryVo.setSysUserName(sysUser.getUserName());
                    }
                }
            }
            if(subTaskQueryVo.getProjectId() != null){
                Project project = projectService.findById(subTaskQueryVo.getProjectId());
                if(project != null){
                    subTaskQueryVo.setProjectName(project.getName());
                }
            }

        });
        pageInfo.setList(subTaskQueryVos);
        //pageInfo.setList(resultList);
        return pageInfo;
    }

    /**
     * 项目任务指派/转交
     * @param projectTaskAssignQo
     * @throws BusinessException
     * @throws Exception
     */
    @Transactional
    public void projectTaskAssign(ProjectTaskAssignQo projectTaskAssignQo) throws BusinessException,Exception{
        //获取当前登录用户
        AdminLoginUser adminLoginUser = super.getAdminLoginUser();
        if(adminLoginUser == null){
            throw new BusinessException(ResultCode.USER_NOT_LOGIN);
        }
        Long id = projectTaskAssignQo.getId();
        ProjectTask projectTask = projectTaskService.findById(id);
        if(projectTask == null){
            throw new BusinessException(ResultCode.DATA_NOT_FOUND);
        }
        projectTask.setSysUid(projectTaskAssignQo.getSysUid());
        projectTaskService.update(projectTask);
        //获取被指派人姓名
        Long receiverId = projectTaskAssignQo.getSysUid();
        //查询后台用户姓名
        String receiverName = "";
        Map<String,Object> employeeParam = new HashMap<>();
        employeeParam.put("isDeleted",0);
        employeeParam.put("sysUid",receiverId);
        employeeParam.put("status",1);
        Employee employee = employeeService.findByModel(employeeParam);
        if(employee == null){
            receiverName = employee.getName();
        }else{
            SysUser sysUser = sysUserService.findById(receiverId);
            receiverName = sysUser.getUserName();
        }
        //存储指派记录
        taskTransferLogService.save(
            TaskTransferLog.builder()
                    .assignId(adminLoginUser.getId())//指派人id
                    .assignName(adminLoginUser.getName())//指派人姓名
                    .receiverName(receiverName)//被指派人姓名
                    .receiverId(receiverId)//被指派人id
                    .assignTime(Instant.now().toEpochMilli())
                    .taskId(projectTask.getId())
                    .createTime(Instant.now().toEpochMilli())
                    .updateTime(Instant.now().toEpochMilli())
                    .isDeleted(0)
                    .build()
        );

    }

    /**
     * 计算两个时间戳相差多少小时
     * @return
     */
    private BigDecimal getHours(Long startTime,Long endTime){
        BigDecimal hour = BigDecimal.ZERO;
        if(startTime != null && endTime != null){
            //计算相差的分钟数
            Long minutes = ChronoUnit.MINUTES.between(LocalDateTime.ofInstant(Instant.ofEpochMilli(startTime), ZoneId.systemDefault()), LocalDateTime.ofInstant(Instant.ofEpochMilli(endTime), ZoneId.systemDefault()));
            BigDecimal b = new BigDecimal(minutes/60);
            hour = b.setScale(2,BigDecimal.ROUND_HALF_UP);
        }
        return hour;
    }

    /**
     * 任务工作记录 修改，修改指定的字段
     * @param editWorkRecordQo
     * @throws BusinessException
     * @throws Exception
     */
    public void editWorkRecord(EditWorkRecordQo editWorkRecordQo) throws BusinessException,Exception{
        Long id = editWorkRecordQo.getId();
        ProjectTask projectTask = projectTaskService.findById(id);
        if(projectTask == null){
            throw new BusinessException(ResultCode.DATA_NOT_FOUND);
        }
        projectTask.setStartTime(editWorkRecordQo.getStartTime());
        projectTask.setEndTime(editWorkRecordQo.getEndTime());
        projectTask.setStatus(editWorkRecordQo.getStatus());
        projectTask.setCompleteResult(editWorkRecordQo.getCompleteResult());
        projectTask.setResultAttachment(editWorkRecordQo.getResultAttachment());
        projectTask.setWorkHours(getHours(editWorkRecordQo.getStartTime(), editWorkRecordQo.getEndTime()));
        projectTaskService.update(projectTask);
    }

    /**
     * 根据父id查询所有子任务集合
     * @param subTaskQueryQo
     * @return
     */
    public PageInfo subTaskQuery(SubTaskQueryQo subTaskQueryQo) throws BusinessException,Exception{
        //把当前项目id当作父id进行查询
        Long parentId = subTaskQueryQo.getId();
        ProjectTask projectTask = projectTaskService.findById(parentId);
        if(projectTask == null){
            throw new BusinessException(ResultCode.DATA_NOT_FOUND);
        }
        //根据父id查询子任务集合
        Condition condition = new Condition(ProjectTask.class);
        Example.Criteria criteria = condition.createCriteria();
        criteria.andEqualTo("parentId",parentId);
        criteria.andEqualTo("isDeleted",ProjectTaskEnum.NOT_DELETE.code());
        PageHelper.startPage(subTaskQueryQo.getPageNum(),subTaskQueryQo.getPageSize());
        List<ProjectTask> projectTaskList = projectTaskService.findByCondition(condition);
        PageInfo pageInfo = new PageInfo<>(projectTaskList);
        List<SubTaskQueryVo> taskQueryVoList = projectTaskList.stream().map(SubTaskQueryVo::new).collect(Collectors.toList());
        List<SubTaskQueryVo> subTaskQueryVos = this.recursiveQuery(taskQueryVoList);
        pageInfo.setList(subTaskQueryVos);
        return pageInfo;
    }


    /**
     * 子任务递归查询
     * @param projectTaskList
     * @return
     */
    public List<SubTaskQueryVo> recursiveQuery(List<SubTaskQueryVo> projectTaskList){
        projectTaskList.stream().forEach(task -> {
            Long nextParentId = task.getId();
            Long parentId = task.getParentId();
            if(nextParentId == parentId){
                //如果当前对象的 父id 等于本身的id 则证明数据有误，会造成死循环，所以这里判断以免造成死循环
                return ;
            }
            //根据父id查询子任务集合
            Condition condition = new Condition(ProjectTask.class);
            Example.Criteria criteria = condition.createCriteria();
            criteria.andEqualTo("parentId",nextParentId);
            criteria.andEqualTo("isDeleted",ProjectTaskEnum.NOT_DELETE.code());
            List<ProjectTask> nextProjectTaskList = projectTaskService.findByCondition(condition);
            //如果子任务下还有子任务则递归查询
            if(!nextProjectTaskList.isEmpty()){
                List<SubTaskQueryVo> taskQueryVoList = nextProjectTaskList.stream().map(SubTaskQueryVo::new).collect(Collectors.toList());
                task.setSubTaskQueryVoList(taskQueryVoList);
                this.recursiveQuery(taskQueryVoList);
            }
        });
        return projectTaskList;
    }

    /**
     * 查询任务详情和指派记录
     * @param subTaskQueryQo
     * @return
     * @throws BusinessException
     * @throws Exception
     */
    public TaskDetailVo taskDetail(SubTaskQueryQo subTaskQueryQo) throws BusinessException,Exception{

        //查询任务详情
        Long id = subTaskQueryQo.getId();
        ProjectTask projectTask = projectTaskService.findById(id);
        if(projectTask == null){
            throw new BusinessException(ResultCode.DATA_NOT_FOUND);
        }
        ProjectTaskListVo projectTaskListVo = new ProjectTaskListVo(projectTask);

        //查询指派记录
        Map<String,Object> taskLogParam = new HashMap<>();
        taskLogParam.put("isDeleted",0);
        taskLogParam.put("taskId",id);
        List<TaskTransferLog> taskTransferLogList = taskTransferLogService.findByConditionMap(taskLogParam);
        List<TaskTransferLogVo> logVoList = null;
        if(taskTransferLogList != null && !taskTransferLogList.isEmpty()){
            logVoList = taskTransferLogList.stream().map(TaskTransferLogVo::new).collect(Collectors.toList());
        }
        return TaskDetailVo.builder()
                .taskDetail(projectTaskListVo)
                .taskTransferLogVoList(logVoList)
                .build();
    }
}
